package com.atm.service;

import com.atm.entity.Account;
import com.atm.entity.CashLog;
import com.atm.entity.DepositLog;
import com.atm.entity.TransferLog;
import com.atm.entity.dto.AccountDTO;
import com.atm.entity.dto.LoginParams;
import com.atm.mapper.AccountMapper;
import com.atm.mapper.CashLogMapper;
import com.atm.mapper.DepositLogMapper;
import com.atm.mapper.TransferLogMapper;
import com.atm.utils.JWTUtil;
import com.atm.utils.result.Result;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class AccountService {

    @Resource
    private AccountMapper accountMapper;
    @Resource
    private DepositLogMapper depositLogMapper;
    @Resource
    private CashLogMapper cashLogMapper;
    @Resource
    private TransferLogMapper transferLogMapper;

    public Result<AccountDTO> login(LoginParams loginParams) {

        Wrapper<Account> wrapper = new QueryWrapper<Account>().eq("accountNo", loginParams.getAccountNo());
        Account account = accountMapper.selectOne(wrapper);
        if (account == null) {
            return Result.fail("登录失败，账户不存在");
        }

        if (!account.getPassword().equals(loginParams.getPassword())) {
            return Result.fail("登录失败，密码不正确");
        }

        AccountDTO accountDTO = new AccountDTO();
        accountDTO.setAccountNo(account.getAccountNo());
        accountDTO.setPassword(account.getPassword());
        accountDTO.setRemainAmount(account.getRemainAmount());
        accountDTO.setLastTime(account.getLastTime());
        accountDTO.setToken(JWTUtil.generateToken(account.getAccountNo(), System.currentTimeMillis() + 3600 * 1000));

        return Result.ok(accountDTO);
    }

    public Result<Account> balance(String accountNo) {
        Account res = accountMapper.selectById(accountNo);

        return Result.ok(res);
    }

    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> deposit(Long depositAmount, String accountNo) {
        int result = accountMapper.deposit(accountNo, depositAmount, new Date());
        if (result != 1) {
            return Result.fail("存款失败");
        }

        // 添加记录
        DepositLog log = new DepositLog();
        log.setAccountNo(accountNo);
        log.setDepositOperateTime(new Date());
        log.setDepositAmount(depositAmount);
        depositLogMapper.insert(log);
        return Result.ok(true);
    }

    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> cash(Long cashAmount, String accountNo) {
        if(cashAmount==null)
            return Result.fail("取款金额不能为空");
        Wrapper<Account> wrapper = new QueryWrapper<Account>().eq("accountNo", accountNo);
        Account res = accountMapper.selectOne(wrapper);
        if (res.getRemainAmount() < cashAmount)
            return Result.fail("余额不足");
        int result = accountMapper.cash(accountNo, cashAmount, new Date());
        if (result != 1)
            return Result.fail("取款失败");

        // 添加记录
        CashLog log = new CashLog();
        log.setAccountNo(accountNo);
        log.setCashOperateTime(new Date());
        log.setCashAmount(cashAmount);
        cashLogMapper.insert(log);
        return Result.ok(true);
    }

    /**
     * 修改密码：新密码长度不小于6位，不允许出现6位完全相同的情况，只有旧密码正确，新密码符合要求，且两次输入相同的情况下才可以成功修改密码。
     *
     * @param oldPassword .
     * @param newPassword .
     */
    @Transactional(rollbackFor = Exception.class) // 事务控制，出现Exception就自动回滚
    public Result<Boolean> modifyPassword(String oldPassword, String newPassword, String repeatPassword, String accountNo) {
        if (oldPassword == null || newPassword == null || repeatPassword == null)
            return Result.fail("输入错误为空");
        if (oldPassword.length() < 6 || oldPassword.length() > 20 || newPassword.length() < 6 || newPassword.length() > 20)
            return Result.fail("密码长度必须为6~20");
        if (!newPassword.equals(repeatPassword))
            return Result.fail("两次新密码不一致");

        for (int i = 0; i + 6 <= oldPassword.length(); i++) {
            if (newPassword.contains(oldPassword.substring(i, i + 6)))
                return Result.fail("新密码和旧密码不能有6位完全相同");
        }

        Account account = accountMapper.selectById(accountNo);
        if (!account.getPassword().equals(oldPassword)) {
            return Result.fail("旧密码不正确");
        }

        account.setPassword(newPassword);
        int updateResult = accountMapper.updateById(account); // 更新数据库
        if (updateResult == 1) {
            return Result.ok(true);
        }

        return Result.fail("修改失败");
    }

    /**
     * @param toAccountId      转给谁
     * @param transferAmount   转多少钱
     * @param currentAccountNo 当前登录的账户
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> transfer(String toAccountId, Long transferAmount, String currentAccountNo) {
        if (transferAmount == null || transferAmount < 0) {
            return Result.fail(("转账金额不合法"));
        }

        Account account = accountMapper.selectById(currentAccountNo);
        Account account1 = accountMapper.selectById(toAccountId);
        if (account.getRemainAmount() < transferAmount) {
            return Result.fail("余额不够");
        }

        // 更新余额
        account.setRemainAmount(account.getRemainAmount() - transferAmount);
        account1.setRemainAmount(account1.getRemainAmount() + transferAmount);
        account.setLastTime(new Date());
        int updateResult1 = accountMapper.updateById(account);
        int updateResult2 = accountMapper.updateById(account1);
        if (updateResult1 != 1 || updateResult2 != 1) {
            return Result.fail("转账失败");
        }

        TransferLog transferLog = new TransferLog();
        transferLog.setFromAccountId(account.getAccountNo());
        transferLog.setToAccountId(toAccountId);
        transferLog.setTransferOperateTime(new Date());
        transferLog.setTransferAmount(transferAmount);
        transferLogMapper.insert(transferLog);

        return Result.ok(true);
    }

    /**
     * @param accountNo 当前登录的卡号
     * @return 用户名
     */
    public Result<String> selectUsernameByAccountNo(String accountNo) {
        String res = accountMapper.selectByAccountNo(accountNo);
        return Result.ok(res);
    }
}
